﻿// demon4-类和对象-1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//类的定义
/*
    class className
 {
    成员函数;
    成员变量组成;
  };  

    class为定义类的关键字，ClassName为类的名字，{}中为类的主体，注意类定义结束时后面分号不能省略。
    类体中内容称为类的成员：类中的变量称为类的属性或成员变量;   类中的函数称为类的方法或者成员函数。
    
    类的两种定义方式：
    1. 声明和定义全部放在类体中，需注意：成员函数如果在类中定义，编译器可能会将其当成内联函数处理。
    一般情况下，更期望采用第二种方式。注意：上课为了方便演示使用方式一定义类，大家后序工作中尽量使用第二种。

    【访问限定符说明】
       1. public修饰的成员在类外可以直接被访问
       2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
       3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
       4. 如果后面没有访问限定符，作用域就到}即类结束。
       5. class的默认访问权限为private，struct为public(因为struct要兼容C)
     注意：访问限定符只在编译时有用，当数据映射到内存后，没有任何访问限定符上的区别
*/

#include <iostream>
using namespace std;

class Date                                                //class默认访问是private私有的，而struct默认public公有的
{
    void Print1()                                         //这里默认是private私有的，类外面不能调用此成员函数
    {
        cout << "调用成员函数Print1打印信息" << endl;
    }
public:
    void Init(int year, int month, int day)              //成员函数，调用私有成员变量_year、_month、_day
    {
        _year = year;
        _month = month;
        _day = day;
    }
    void Print2()                                        //公有成员函数，类外面可进行调用
    {
        cout << _year << "/" << _month << "/" << _day << endl;   //调用类成员变量
    }
    int fp = 1;
    void Print3(int x);
private:                                                 //一般成员变量设置为私有的，外部往往通过调用成员函数
    int _year=0;                                         //声明成员变量_year、_month、_day
    int _month=0;
    int _day=0;
};

void Date::Print3(int x)
{
    cout << "类外面调用Print3()函数"<<x<<"次" << endl;
}

class A2
{
public:
    void f2(){}
};

class A3
{};

int main()
{
    Date d1;                         //这里才是定义，即对象实例化
    d1.Init(2024, 8, 25);
    //d1.Print1();                   //无法调用私有的类成员函数Print1()
    d1.Print2();
    d1.Print3(1);
    //Date::fp++;                    //不能访问，因为类里面的int fp仅仅是声明，不是定义，不能直接访问
    d1.fp++;                         //只能访问公有的成员变量

    cout << "sizeof(d1) = " << sizeof(d1) << endl<<endl;      //讲究内存对齐，sizeof(d1) = 16字节
    //因为成员函数没有存在类的对象里面，而是找一块公共区域来存放成员函数，所以是16字节

    //例如
    Date d2;                         
    Date d3;

    d2.fp++;                         //这两个fp不一样，不是同一块空间的成员变量  
    d3.fp++;

    d2.Print3(1);
    d3.Print3(1);                    //但是这两个成员函数是同一块空间，成员函数的地址是一样的
    
    //两个类都没有成员变量，类大小默认为1字节，作为占位作用，在标识对象实例化时，定义出来存在过
    cout << "sizeof(A2) = " << sizeof(A2) << endl;                   //sizeof(A2) = 1
    cout << "sizeof(A3) = " << sizeof(A3) << endl;                   //sizeof(A3) = 1
    
    //此时标识对象需要开空间，所以没有成员变量的类大小不能是0，而是1
    A2 aa1;
    A3 bb2;  
}
